//
//  MDHRACExtension.m
//  MDHPT
//
//  Created by 高得华 on 2019/4/23.
//  Copyright © 2019年 高得华. All rights reserved.
//

#import "MDHRACExtension.h"
#import <objc/runtime.h>

#if __has_include("MDHPT/MDHPT-Swift.h")
#import "MDHPT/MDHPT-Swift.h"
#else
#import "MDHPT-Swift.h"
#endif

@implementation MDHRACExtension
@end


//MARK: - ==== MDHHTTPServiceAdditions
///从MDHHTTPServiceAdditions检索分析结果的便利类别。
@implementation RACSignal (MDHHTTPServiceAdditions)

// This method assumes that the receiver is a signal of MHHTTPResponses.
//
// Returns a signal that maps the receiver to become a signal of
// MHHTTPResponses.parsedResult.
- (RACSignal *)mdh_parsedResults {
    return [self map:^id(MDHHTTPResponse * value) {
        NSAssert([value isKindOfClass:MDHHTTPResponse.class], @"Expected %@ to be an MDHHTTPResponse.", value);
        return value;
    }];
}

@end


//MARK: - ===== AFHTTPSessionManager
@implementation AFHTTPSessionManager (RACSupport)

/// A convenience around -GET:parameters:success:failure: that returns a cold signal of the
/// resulting JSON object and response headers or error.
- (RACSignal *)rac_GET:(NSString *)path parameters:(id)parameters {
    return [[self rac_requestPath:path parameters:parameters method:MMWPT_HTTTP_METHOD_GET] setNameWithFormat:@"%@ -rac_GET: %@, parameters: %@", self.class, path, parameters];
}

/// A convenience around -HEAD:parameters:success:failure: that returns a cold signal of the
/// resulting JSON object and response headers or error.
- (RACSignal *)rac_HEAD:(NSString *)path parameters:(id)parameters {
    return [[self rac_requestPath:path parameters:parameters method:MMWPT_HTTTP_METHOD_HEAD]
            setNameWithFormat:@"%@ -rac_HEAD: %@, parameters: %@", self.class, path, parameters];
}

/// A convenience around -POST:parameters:success:failure: that returns a cold signal of the
/// result.
- (RACSignal *)rac_POST:(NSString *)path parameters:(id)parameters {
    return [[self rac_requestPath:path parameters:parameters method:MMWPT_HTTTP_METHOD_POST]
            setNameWithFormat:@"%@ -rac_POST: %@, parameters: %@", self.class, path, parameters];
}

/// A convenience around -POST:parameters:constructingBodyWithBlock:success:failure: that returns a
/// cold signal of the resulting JSON object and response headers or error.
- (RACSignal *)rac_POST:(NSString *)path parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block {
    return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:MMWPT_HTTTP_METHOD_POST URLString:[[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil];
        NSURLSessionDataTask * task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
            if (error) {
                NSMutableDictionary * userInfo = [error.userInfo mutableCopy];
                if (responseObject) {
                    userInfo[RACAFNResponseObjectErrorKey] = responseObject;
                }
                NSError *errorWithRes = [NSError errorWithDomain:error.domain code:error.code userInfo:[userInfo copy]];
                [subscriber sendError:errorWithRes];
            }else{
                [subscriber sendNext:RACTuplePack(responseObject, response)];
            }
            [subscriber sendCompleted];
        }];
        [task resume];
        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }] setNameWithFormat:@"%@ -rac_POST: %@, parameters: %@, constructingBodyWithBlock:",self.class, path, parameters];
}

/// A convenience around -PUT:parameters:success:failure: that returns a cold signal of the
/// resulting JSON object and response headers or error.
- (RACSignal *)rac_PUT:(NSString *)path parameters:(id)parameters {
    return [[self rac_requestPath:path parameters:parameters method:MMWPT_HTTTP_METHOD_PUT]
            setNameWithFormat:@"%@ -rac_PUT: %@, parameters: %@",self.class, path, parameters];
}

/// A convenience around -PATCH:parameters:success:failure: that returns a cold signal of the
/// resulting JSON object and response headers or error.
- (RACSignal *)rac_PATCH:(NSString *)path parameters:(id)parameters {
    return [[self rac_requestPath:path parameters:parameters method:MMWPT_HTTTP_METHOD_PATCH]
            setNameWithFormat:@"%@ -rac_PATCH: %@, parameters: %@", self.class, path, parameters];
}

/// A convenience around -DELETE:parameters:success:failure: that returns a cold signal of the
/// resulting JSON object and response headers or error.
- (RACSignal *)rac_DELETE:(NSString *)path parameters:(id)parameters {
    return [[self rac_requestPath:path parameters:parameters method:MMWPT_HTTTP_METHOD_DELETE]
            setNameWithFormat:@"%@ -rac_DELETE: %@, parameters: %@", self.class, path, parameters];
}


//MARK: -==== 私有方法
- (RACSignal *)rac_requestPath:(NSString *)path parameters:(id)parameters method:(NSString *)method {
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        /// 获取request
        NSURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
        
        NSURLSessionDataTask * task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
            if (error) {
                NSMutableDictionary * userInfo = [error.userInfo mutableCopy];
                if (responseObject) {
                    userInfo[RACAFNResponseObjectErrorKey] = responseObject;
                }
                NSError * err = [NSError errorWithDomain:error.domain code:error.code userInfo:[userInfo copy]];
                [subscriber sendError:err];
            }else{
                [subscriber sendNext:RACTuplePack(responseObject, response)];
            }
            [subscriber sendCompleted];
        }];
        [task resume];
        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }];
}

@end

